home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2007 December / PCWKCD1207B.iso / Blogowanie poza sfera / Flock 0.9.1.3 stable / flock-0.9.1.3.en-US.win32.exe / flock / chrome / browser.jar / content / browser / pageInfo.js < prev    next >
Text File  |  2006-07-18  |  35KB  |  1,066 lines

  1. //@line 42 "/cygdrive/K/tinderbuild/src/flock/mozilla/browser/base/content/pageInfo.js"
  2.  
  3. //******** define a js object to implement nsITreeView
  4. function pageInfoTreeView(columnids, copycol)
  5. {
  6.   // columnids is an array of strings indicating the names of the columns, in order
  7.   this.columnids = columnids;
  8.   this.colcount = columnids.length
  9.  
  10.   // copycol is the index number for the column that we want to add to 
  11.   // the copy-n-paste buffer when the user hits accel-c
  12.   this.copycol = copycol;
  13.   this.rows = 0;
  14.   this.tree = null;
  15.   this.data = new Array;
  16.   this.selection = null;
  17.   this.sortcol = null;
  18.   this.sortdir = 0;
  19. }
  20.  
  21. pageInfoTreeView.prototype = {
  22.   set rowCount(c) { throw "rowCount is a readonly property"; },
  23.   get rowCount() { return this.rows; },
  24.  
  25.   setTree: function(tree) 
  26.   {
  27.     this.tree = tree;
  28.   },
  29.  
  30.   getCellText: function(row, column)
  31.   {
  32.     // row can be null, but js arrays are 0-indexed.
  33.     // colidx cannot be null, but can be larger than the number
  34.     // of columns in the array (when column is a string not in 
  35.     // this.columnids.) In this case it's the fault of
  36.     // whoever typoed while calling this function.
  37.     return this.data[row][column.index] || "";
  38.   },
  39.  
  40.   setCellValue: function(row, column, value) 
  41.   {
  42.   },
  43.  
  44.   setCellText: function(row, column, value) 
  45.   {
  46.     this.data[row][column.index] = value;
  47.   },
  48.  
  49.   addRow: function(row)
  50.   {
  51.     this.rows = this.data.push(row);
  52.     this.rowCountChanged(this.rows - 1, 1);
  53.   },
  54.  
  55.   addRows: function(rows)
  56.   {
  57.     var length = rows.length;
  58.     for(var i = 0; i < length; i++)
  59.       this.rows = this.data.push(rows[i]);
  60.     this.rowCountChanged(this.rows - length, length);
  61.   },
  62.  
  63.   rowCountChanged: function(index, count)
  64.   {
  65.     this.tree.rowCountChanged(index, count);
  66.   },
  67.  
  68.   invalidate: function()
  69.   {
  70.     this.tree.invalidate();
  71.   },
  72.  
  73.   clear: function()
  74.   {
  75.     this.data = new Array;
  76.     this.rows = 0;
  77.   },
  78.  
  79.   handleCopy: function(row)
  80.   {
  81.     return (row < 0 || this.copycol < 0) ? "" : (this.data[row][this.copycol] || "");
  82.   },
  83.  
  84.   performActionOnRow: function(action, row)
  85.   {
  86.     if (action == "copy")
  87.     {
  88.       var data = this.handleCopy(row)
  89.       this.tree.treeBody.parentNode.setAttribute("copybuffer", data);
  90.     }
  91.   },
  92.  
  93.   getRowProperties: function(row, prop) { },
  94.   getCellProperties: function(row, column, prop) { },
  95.   getColumnProperties: function(column, prop) { },
  96.   isContainer: function(index) { return false; },
  97.   isContainerOpen: function(index) { return false; },
  98.   isSeparator: function(index) { return false; },
  99.   isSorted: function() { },
  100.   canDrop: function(index, orientation) { return false; },
  101.   drop: function(row, orientation) { return false; },
  102.   getParentIndex: function(index) { return 0; },
  103.   hasNextSibling: function(index, after) { return false; },
  104.   getLevel: function(index) { return 0; },
  105.   getImageSrc: function(row, column) { },
  106.   getProgressMode: function(row, column) { },
  107.   getCellValue: function(row, column) { },
  108.   toggleOpenState: function(index) { },
  109.   cycleHeader: function(col) { },
  110.   selectionChanged: function() { },
  111.   cycleCell: function(row, column) { },
  112.   isEditable: function(row, column) { return false; },
  113.   performAction: function(action) { },
  114.   performActionOnCell: function(action, row, column) { }
  115. };
  116.  
  117. // mmm, yummy. global variables.
  118. var theWindow = null;
  119. var theDocument = null;
  120.  
  121. // column number to copy from, second argument to pageInfoTreeView's constructor
  122. const COPYCOL_NONE = -1;
  123. const COPYCOL_META_CONTENT = 1;
  124. const COPYCOL_FORM_ACTION = 2;
  125. const COPYCOL_LINK_ADDRESS = 1;
  126. const COPYCOL_IMAGE_ADDRESS = 0;
  127.  
  128. // one nsITreeView for each tree in the window
  129. var metaView = new pageInfoTreeView(["meta-name","meta-content"], COPYCOL_META_CONTENT);
  130. var formView = new pageInfoTreeView(["form-name","form-method","form-action","form-node"], COPYCOL_FORM_ACTION);
  131. var fieldView = new pageInfoTreeView(["field-label","field-field","field-type","field-value"], COPYCOL_NONE);
  132. var linkView = new pageInfoTreeView(["link-name","link-address","link-type","link-accesskey"], COPYCOL_LINK_ADDRESS);
  133. var imageView = new pageInfoTreeView(["image-address","image-type","image-alt","image-count","image-node","image-bg"], COPYCOL_IMAGE_ADDRESS);
  134.  
  135. var imageHash = {};
  136.  
  137. var kmsPerSec = 1000;
  138.  
  139. // localized strings (will be filled in when the document is loaded)
  140. // this isn't all of them, these are just the ones that would otherwise have been loaded inside a loop
  141. var gStrings = {}
  142. var theBundle;
  143.  
  144. const DRAGSERVICE_CONTRACTID    = "@mozilla.org/widget/dragservice;1";
  145. const TRANSFERABLE_CONTRACTID   = "@mozilla.org/widget/transferable;1";
  146. const ARRAY_CONTRACTID          = "@mozilla.org/supports-array;1";
  147. const STRING_CONTRACTID         = "@mozilla.org/supports-string;1";
  148.  
  149. // a number of services I'll need later
  150. // the cache services
  151. const nsICacheService = Components.interfaces.nsICacheService;
  152. const cacheService = Components.classes["@mozilla.org/network/cache-service;1"].getService(nsICacheService);
  153. var httpCacheSession = cacheService.createSession("HTTP", 0, true);
  154. httpCacheSession.doomEntriesIfExpired = false;
  155. var ftpCacheSession = cacheService.createSession("FTP", 0, true);
  156. ftpCacheSession.doomEntriesIfExpired = false;
  157.  
  158. // scriptable date formater, for pretty printing dates
  159. const nsIScriptableDateFormat = Components.interfaces.nsIScriptableDateFormat;
  160. var dateService = Components.classes["@mozilla.org/intl/scriptabledateformat;1"].getService(nsIScriptableDateFormat);
  161.  
  162. // clipboard helper
  163. try
  164. {
  165.   const gClipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"].getService(Components.interfaces.nsIClipboardHelper);
  166. }
  167. catch(e)
  168. {
  169.   // do nothing, later code will handle the error
  170. }
  171.  
  172. // interfaces for the different html elements
  173. const nsIAnchorElement   = Components.interfaces.nsIDOMHTMLAnchorElement
  174. const nsIImageElement    = Components.interfaces.nsIDOMHTMLImageElement
  175. const nsIAreaElement     = Components.interfaces.nsIDOMHTMLAreaElement
  176. const nsILinkElement     = Components.interfaces.nsIDOMHTMLLinkElement
  177. const nsIInputElement    = Components.interfaces.nsIDOMHTMLInputElement
  178. const nsIFormElement     = Components.interfaces.nsIDOMHTMLFormElement
  179. const nsIAppletElement   = Components.interfaces.nsIDOMHTMLAppletElement
  180. const nsIObjectElement   = Components.interfaces.nsIDOMHTMLObjectElement
  181. const nsIEmbedElement    = Components.interfaces.nsIDOMHTMLEmbedElement
  182. const nsIButtonElement   = Components.interfaces.nsIDOMHTMLButtonElement
  183. const nsISelectElement   = Components.interfaces.nsIDOMHTMLSelectElement
  184. const nsITextareaElement = Components.interfaces.nsIDOMHTMLTextAreaElement
  185. const nsIQuoteElement    = Components.interfaces.nsIDOMHTMLQuoteElement
  186. const nsIModElement      = Components.interfaces.nsIDOMHTMLModElement
  187.  
  188. // Interface for image loading content
  189. const nsIImageLoadingContent = Components.interfaces.nsIImageLoadingContent;
  190.  
  191. // namespaces, don't need all of these yet...
  192. const XLinkNS  = "http://www.w3.org/1999/xlink";
  193. const XULNS    = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
  194. const XMLNS    = "http://www.w3.org/XML/1998/namespace";
  195. const XHTMLNS  = "http://www.w3.org/1999/xhtml";
  196. const XHTML2NS = "http://www.w3.org/2002/06/xhtml2"
  197.  
  198. const XHTMLNSre  = "^http\:\/\/www\.w3\.org\/1999\/xhtml$";
  199. const XHTML2NSre = "^http\:\/\/www\.w3\.org\/2002\/06\/xhtml2$";
  200. const XHTMLre = RegExp(XHTMLNSre + "|" + XHTML2NSre, "");
  201.  
  202. /* Overlays register init functions here.
  203.  *   Add functions to call by invoking "onLoadRegistry.append(XXXLoadFunc);"
  204.  *   The XXXLoadFunc should be unique to the overlay module, and will be
  205.  *   invoked as "XXXLoadFunc();"
  206.  */
  207. var onLoadRegistry = [ ];
  208.  
  209. /* Called when PageInfo window is loaded.  Arguments are:
  210.  *  window.arguments[0] - (optional) an object consisting of
  211.  *                         - doc: (optional) document to use for source. if not provided, 
  212.  *                                the calling window's document will be used
  213.  *                         - initialTab: (optional) id of the inital tab to display
  214.  */
  215. function onLoadPageInfo()
  216. {
  217.   //dump("===============================================================================\n");
  218.  
  219.   theBundle = document.getElementById("pageinfobundle");
  220.   gStrings.unknown = theBundle.getString("unknown");
  221.   gStrings.notSet = theBundle.getString("notset");
  222.   gStrings.emptyString = theBundle.getString("emptystring");
  223.   gStrings.noExpiration = theBundle.getString("generalNoExpiration");
  224.   gStrings.linkAnchor = theBundle.getString("linkAnchor");
  225.   gStrings.linkArea = theBundle.getString("linkArea");
  226.   gStrings.linkSubmit = theBundle.getString("linkSubmit");
  227.   gStrings.linkSubmission = theBundle.getString("linkSubmission");
  228.   gStrings.linkRel = theBundle.getString("linkRel");
  229.   gStrings.linkStylesheet = theBundle.getString("linkStylesheet");
  230.   gStrings.linkRev = theBundle.getString("linkRev");
  231.   gStrings.linkX = theBundle.getString("linkX");
  232.   gStrings.linkQuote = theBundle.getString("linkQuote");
  233.   gStrings.linkMod = theBundle.getString("linkMod");
  234.   gStrings.mediaImg = theBundle.getString("mediaImg");
  235.   gStrings.mediaBGImg = theBundle.getString("mediaBGImg");
  236.   gStrings.mediaApplet = theBundle.getString("mediaApplet");
  237.   gStrings.mediaObject = theBundle.getString("mediaObject");
  238.   gStrings.mediaEmbed = theBundle.getString("mediaEmbed");
  239.   gStrings.mediaLink = theBundle.getString("mediaLink");
  240.   gStrings.mediaInput = theBundle.getString("mediaInput");
  241.  
  242.   var docTitle = "";
  243.   if ("arguments" in window && window.arguments.length >= 1 &&
  244.        window.arguments[0] && window.arguments[0].doc)
  245.   {
  246.     theWindow = null;
  247.     theDocument = window.arguments[0].doc;
  248.     docTitle = theBundle.getString("frameInfo.title");
  249.   } 
  250.   else 
  251.   {
  252.     if ("gBrowser" in window.opener)
  253.       theWindow = window.opener.gBrowser.contentWindow;
  254.     else
  255.       theWindow = window.opener.frames[0];
  256.     theDocument = theWindow.document;
  257.  
  258.     docTitle = theBundle.getString("pageInfo.title");
  259.   }
  260.  
  261.   document.title = docTitle;
  262.   
  263.   document.getElementById("main-window").setAttribute("relatedUrl", theDocument.location.toString());
  264.  
  265.   // do the easy stuff first
  266.   makeGeneralTab();
  267.  
  268.   // and then the hard stuff
  269.   makeTabs(theDocument, theWindow);
  270.  
  271.   /* Call registered overlay init functions */
  272.   for (x in onLoadRegistry)
  273.   {
  274.     onLoadRegistry[x]();
  275.   }
  276.  
  277.   /* Select the requested tab, if the name is specified */
  278.   var tabControl = document.getElementById("tabbox");
  279.   if ("arguments" in window && window.arguments.length >= 1 &&
  280.        window.arguments[0] && window.arguments[0].initialTab)
  281.   {
  282.     var tab = document.getElementById(window.arguments[0].initialTab);
  283.     if (tab)
  284.     {
  285.       tabControl.selectedTab = tab;
  286.     }
  287.   }
  288.   tabControl.selectedTab.focus();
  289. }
  290.  
  291. function doHelpButton() {
  292.   var helpdoc;
  293.   var tabControl = document.getElementById("tabbox");
  294.   switch (tabControl.selectedTab.id) {
  295.     case "generalTab":
  296.       helpdoc = "pageinfo_general";
  297.       break;
  298.     case "formsTab":
  299.       helpdoc = "pageinfo_forms";
  300.       break;
  301.     case "linksTab":
  302.       helpdoc = "pageinfo_links";
  303.       break;
  304.     case "mediaTab":
  305.       helpdoc = "pageinfo_media";
  306.       break;
  307.     case "securityTab":
  308.       helpdoc = "pageinfo_security";
  309.       break;
  310.     case "p3pTab":
  311.       helpdoc = "pageinfo_privacy";
  312.       break;
  313.     default:
  314.       helpdoc = "pageinfo_general";
  315.       break;
  316.   }
  317.   openHelp(helpdoc, 'chrome://browser/locale/help/help.rdf');
  318. }
  319.  
  320. function makeGeneralTab()
  321. {
  322.   var title = (theDocument.title) ? theBundle.getFormattedString("pageTitle", [theDocument.title]) : theBundle.getString("noPageTitle");
  323.   document.getElementById("titletext").value = title;
  324.  
  325.   var url = theDocument.location.toString();
  326.   setItemValue("urltext", url, gStrings.unknown);
  327.  
  328.   var mode = ("compatMode" in theDocument && theDocument.compatMode == "BackCompat") ? theBundle.getString("generalQuirksMode") : theBundle.getString("generalStrictMode");
  329.   document.getElementById("modetext").value = mode;
  330.  
  331.   var referrer = ("referrer" in theDocument && theDocument.referrer);
  332.   setItemValue("refertext", referrer);
  333.  
  334.   // find out the mime type
  335.   var mimeType = theDocument.contentType;
  336.   setItemValue("typetext", mimeType, gStrings.unknown);
  337.   
  338.   // get the meta tags
  339.   var metaNodes = theDocument.getElementsByTagName("meta");
  340.   var metaTree = document.getElementById("metatree");
  341.  
  342.   metaTree.treeBoxObject.view = metaView;
  343.  
  344.   var length = metaNodes.length;
  345.   for (var i = 0; i < length; i++)
  346.     metaView.addRow([metaNodes[i].name || metaNodes[i].httpEquiv, metaNodes[i].content]);
  347.  
  348.   // get the document characterset
  349.   var encoding = theDocument.characterSet;
  350.   document.getElementById("encodingtext").value = encoding;
  351.  
  352.   // get the date of last modification
  353.   var modifiedText = formatDate(theDocument.lastModified, gStrings.notSet);
  354.   document.getElementById("modifiedtext").value = modifiedText;
  355.   
  356.   // get cache info
  357.   var sourceText;
  358.   var expirationText;
  359.   var sizeText;
  360.  
  361.   var pageSize = 0; 
  362.   var kbSize = 0;
  363.   var expirationTime = 0;
  364.  
  365.   var cacheKey = url.replace(/#.*$/, "");
  366.   try
  367.   {
  368.     var cacheEntryDescriptor = httpCacheSession.openCacheEntry(cacheKey, Components.interfaces.nsICache.ACCESS_READ, false);
  369.     if (cacheEntryDescriptor)
  370.     { 
  371.       switch(cacheEntryDescriptor.deviceID)
  372.       {
  373.         case "disk":
  374.           sourceText = theBundle.getString("generalDiskCache");
  375.           break;
  376.         case "memory":
  377.           sourceText = theBundle.getString("generalMemoryCache");
  378.           break;
  379.         default:
  380.           sourceText = cacheEntryDescriptor.deviceID;
  381.           break;
  382.       }
  383.     }
  384.   }
  385.   catch(ex)
  386.   {
  387.     try
  388.     {
  389.       cacheEntryDescriptor = ftpCacheSession.openCacheEntry(cacheKey, Components.interfaces.nsICache.ACCESS_READ, false);
  390.       if (cacheEntryDescriptor)
  391.       {
  392.         switch(cacheEntryDescriptor.deviceID)
  393.         {
  394.           case "disk":
  395.             sourceText = theBundle.getString("generalDiskCache");
  396.             break;
  397.           case "memory":
  398.             sourceText = theBundle.getString("generalMemoryCache");
  399.             break;
  400.           default:
  401.             sourceText = cacheEntryDescriptor.deviceID;
  402.             break;
  403.         }
  404.       }
  405.     }
  406.     catch(ex2)
  407.     {
  408.     }
  409.   }
  410.  
  411.   if (cacheEntryDescriptor)
  412.   {
  413.     pageSize = cacheEntryDescriptor.dataSize;
  414.     kbSize = pageSize / 1024;
  415.     sizeText = theBundle.getFormattedString("generalSize", [formatNumber(Math.round(kbSize*100)/100), formatNumber(pageSize)]);
  416.  
  417.     expirationText = formatDate(cacheEntryDescriptor.expirationTime*kmsPerSec, gStrings.notSet);
  418.   }
  419.  
  420.   setItemValue("sourcetext", sourceText, theBundle.getString("generalNotCached"));
  421.   setItemValue("expirestext", expirationText, gStrings.noExpiration);
  422.   setItemValue("sizetext", sizeText, gStrings.unknown);
  423. }
  424.  
  425. //******** Generic Build-a-tab
  426. // Assumes the views are empty. Only called once to build the tabs, and
  427. // does so by farming the task off to another thread via setTimeout().
  428. // The actual work is done with a TreeWalker that calls doGrab() once for
  429. // each element node in the document.
  430.  
  431. function makeTabs(aDocument, aWindow)
  432. {
  433.   if (aWindow && aWindow.frames.length > 0)
  434.   {
  435.     var num = aWindow.frames.length;
  436.     for (var i = 0; i < num; i++)
  437.       makeTabs(aWindow.frames[i].document, aWindow.frames[i]);  // recurse through the frames
  438.   }
  439.  
  440.   var formTree = document.getElementById("formtree");
  441.   var linkTree = document.getElementById("linktree");
  442.   var imageTree = document.getElementById("imagetree");
  443.  
  444.   formTree.treeBoxObject.view = formView;
  445.   linkTree.treeBoxObject.view = linkView;
  446.   imageTree.treeBoxObject.view = imageView;
  447.   
  448.   var iterator = aDocument.createTreeWalker(aDocument, NodeFilter.SHOW_ELEMENT, grabAll, true);
  449.   setTimeout(doGrab, 16, iterator);
  450. }
  451.  
  452. function doGrab(iterator)
  453. {
  454.   for (var i = 0; i < 50; ++i)
  455.     if (!iterator.nextNode())
  456.       return;
  457.  
  458.   setTimeout(doGrab, 16, iterator);
  459. }
  460.  
  461. function ensureSelection(view)
  462. {
  463.   // only select something if nothing is currently selected
  464.   // and if there's anything to select
  465.   if (view.selection.count == 0 && view.rowCount)
  466.     view.selection.select(0);
  467. }
  468.  
  469. function addImage(url, type, alt, elem, isBg)
  470. {
  471.   if (url == "")
  472.     return;
  473.   if (!(url in imageHash))
  474.     imageHash[url] = {};
  475.   if (!(type in imageHash[url]))
  476.     imageHash[url][type] = {};
  477.   if (!(alt in imageHash[url][type])) {
  478.     imageHash[url][type][alt] = imageView.data.length;
  479.     imageView.addRow([url, type, alt, 1, elem, isBg]);
  480.   } else {
  481.     var i = imageHash[url][type][alt];
  482.     imageView.data[i][3]++;
  483.   }
  484. }
  485.  
  486. function grabAll(elem)
  487. {
  488.   // check for background images, any node may have one
  489.   var ComputedStyle = elem.ownerDocument.defaultView.getComputedStyle(elem, "");
  490.   var url = ComputedStyle && ComputedStyle.getPropertyCSSValue("background-image");
  491.   if (url && url.primitiveType == CSSPrimitiveValue.CSS_URI)
  492.     addImage(url.getStringValue(), gStrings.mediaBGImg, gStrings.notSet, elem, true);
  493.  
  494.   // one swi^H^H^Hif-else to rule them all
  495.   if (elem instanceof nsIAnchorElement)
  496.     linkView.addRow([getValueText(elem), elem.href, gStrings.linkAnchor, elem.target, elem.accessKey]);
  497.   else if (elem instanceof nsIImageElement)
  498.     addImage(elem.src, gStrings.mediaImg, (elem.hasAttribute("alt")) ? elem.alt : gStrings.notSet, elem, false);
  499.   else if (elem instanceof nsIAreaElement)
  500.     linkView.addRow([elem.alt, elem.href, gStrings.linkArea, elem.target]);
  501.   else if (elem instanceof nsIQuoteElement && elem.cite)
  502.     linkView.addRow([getValueText(elem), elem.cite, gStrings.linkQuote]);
  503.   else if (elem instanceof nsIModElement && elem.cite)
  504.     linkView.addRow([getValueText(elem), elem.cite, gStrings.linkMod]);
  505.   else if (elem instanceof nsILinkElement)
  506.   {
  507.     if (elem.rel)
  508.     {
  509.       var rel = elem.rel;
  510.       if (/\bicon\b/i.test(rel))
  511.         addImage(elem.href, gStrings.mediaLink, "", elem, false);
  512.       else if (/\bstylesheet\b/i.test(rel))
  513.         linkView.addRow([elem.rel, elem.href, gStrings.linkStylesheet, elem.target]);
  514.       else
  515.         linkView.addRow([elem.rel, elem.href, gStrings.linkRel, elem.target]);
  516.     }
  517.     else
  518.       linkView.addRow([elem.rev, elem.href, gStrings.linkRev, elem.target]);
  519.   }
  520.   else if (elem instanceof nsIInputElement || elem instanceof nsIButtonElement)
  521.   {
  522.     switch (elem.type.toLowerCase())
  523.     {
  524.       case "image":
  525.         addImage(elem.src, gStrings.mediaInput, (elem.hasAttribute("alt")) ? elem.alt : gStrings.notSet, elem, false);
  526.         // Fall through, <input type="image"> submits, too
  527.       case "submit":
  528.         if ("form" in elem && elem.form)
  529.         {
  530.           linkView.addRow([elem.value || getValueText(elem) || gStrings.linkSubmit, elem.form.action, gStrings.linkSubmission, elem.form.target]);
  531.         }
  532.         else
  533.           linkView.addRow([elem.value || getValueText(elem) || gStrings.linkSubmit, '', gStrings.linkSubmission, '']);
  534.     }
  535.   }
  536.   else if (elem instanceof nsIFormElement)
  537.   {
  538.     formView.addRow([elem.name, elem.method, elem.action, elem]);
  539.   }
  540.   else if (elem instanceof nsIAppletElement)
  541.   {
  542.     //XXX When Java is enabled, the DOM model for <APPLET> is broken. Bug #59686.
  543.     // Also, some reports of a crash with Java in Media tab (bug 136535), and mixed
  544.     // content from two hosts (bug 136539) so just drop applets from Page Info when
  545.     // Java is on. For the 1.0.1 branch; get a real fix on the trunk.
  546.     if (!navigator.javaEnabled())
  547.       addImage(elem.code || elem.object, gStrings.mediaApplet, "", elem, false);
  548.   }
  549.   else if (elem instanceof nsIObjectElement)
  550.     addImage(elem.data, gStrings.mediaObject, getValueText(elem), elem, false);
  551.   else if (elem instanceof nsIEmbedElement)
  552.     addImage(elem.src, gStrings.mediaEmbed, "", elem, false);
  553.   else if (elem.hasAttributeNS(XLinkNS, "href")) {
  554.     var ioService = Components.classes["@mozilla.org/network/io-service;1"]
  555.                               .getService(Components.interfaces.nsIIOService);
  556.     var href = elem.getAttributeNS(XLinkNS, "href");
  557.     try {
  558.       var baseURI = ioService.newURI(elem.baseURI,
  559.                                      elem.ownerDocument.characterSet, null);
  560.       var uri = ioService.newURI(href, elem.ownerDocument.characterSet,
  561.                                  baseURI).spec;
  562.     } catch (e) {}
  563.     linkView.addRow([getValueText(elem), uri, gStrings.linkX, ""]);
  564.   }
  565.   return NodeFilter.FILTER_ACCEPT;
  566. }
  567.  
  568. //******** Form Stuff
  569. function onFormSelect()
  570. {
  571.   var formTree = document.getElementById("formtree");
  572.   if (!formView.rowCount) return;
  573.  
  574.   if (formView.selection.count == 1)
  575.   {
  576.     var formPreview = document.getElementById("formpreview");
  577.     fieldView.clear();
  578.     formPreview.treeBoxObject.view = fieldView;
  579.  
  580.     var clickedRow = formView.selection.currentIndex;
  581.     // form-node;
  582.     var form = formView.data[clickedRow][3];
  583.  
  584.     var ft = null;
  585.     if (form.name)
  586.       ft = theBundle.getFormattedString("formTitle", [form.name]);
  587.  
  588.     setItemValue("formenctype", form.encoding, theBundle.getString("default"));
  589.     setItemValue("formtarget", form.target, theBundle.getString("formDefaultTarget"));
  590.     document.getElementById("formname").value = ft || theBundle.getString("formUntitled");
  591.  
  592.     var formfields = form.elements;
  593.  
  594.     var length = formfields.length;
  595.  
  596.     var checked = theBundle.getString("formChecked");
  597.     var unchecked = theBundle.getString("formUnchecked");    
  598.  
  599.     for (var i = 0; i < length; i++)
  600.     {
  601.       var elem = formfields[i], val;
  602.  
  603.       if (elem instanceof nsIButtonElement)
  604.         val = getValueText(elem);
  605.       else
  606.         val = (/^password$/i.test(elem.type)) ? theBundle.getString("formPassword") : elem.value;
  607.  
  608.       fieldView.addRow(["", elem.name, elem.type, val]);
  609.     }
  610.  
  611.     var labels = form.getElementsByTagName("label");
  612.     var llength = labels.length;
  613.     var label;
  614.  
  615.     for (i = 0; i < llength; i++)
  616.     {
  617.       label = labels[i];
  618.       var whatfor = label.hasAttribute("for") ?
  619.         theDocument.getElementById(label.getAttribute("for")) :
  620.         findFirstControl(label);
  621.  
  622.       if (whatfor && (whatfor.form == form)) 
  623.       {
  624.         var labeltext = getValueText(label);
  625.         for (var j = 0; j < length; j++)
  626.           if (formfields[j] == whatfor) {
  627.             var col = formPreview.columns["field-label"];
  628.             fieldView.setCellText(j, col, labeltext);
  629.           }
  630.       }
  631.     }
  632.   }
  633. }
  634.  
  635. function FormControlFilter(node) 
  636. {
  637.   if (node instanceof nsIInputElement || node instanceof nsISelectElement ||
  638.       node instanceof nsIButtonElement || node instanceof nsITextareaElement ||
  639.       node instanceof nsIObjectElement)
  640.       return NodeFilter.FILTER_ACCEPT;
  641.     return NodeFilter.FILTER_SKIP;
  642. }
  643.  
  644. function findFirstControl(node)
  645. {
  646.   var iterator = theDocument.createTreeWalker(node, NodeFilter.SHOW_ELEMENT, FormControlFilter, true);
  647.  
  648.   return iterator.nextNode();
  649. }
  650.  
  651. //******** Link Stuff
  652. function openURL(target)
  653. {
  654.   var url = target.parentNode.childNodes[2].value;
  655.   window.open(url, "_blank", "chrome");
  656. }
  657.  
  658. function onBeginLinkDrag(event,urlField,descField)
  659. {
  660.   if (event.originalTarget.localName != "treechildren")
  661.     return;
  662.  
  663.   var tree = event.target;
  664.   if (!("treeBoxObject" in tree))
  665.     tree = tree.parentNode;
  666.  
  667.   var row = tree.treeBoxObject.getRowAt(event.clientX, event.clientY);
  668.   if (row == -1)
  669.     return;
  670.  
  671.   // Getting drag-system needed services
  672.   var dragService = Components.classes[DRAGSERVICE_CONTRACTID].getService().QueryInterface(Components.interfaces.nsIDragService);
  673.   var transArray = Components.classes[ARRAY_CONTRACTID].createInstance(Components.interfaces.nsISupportsArray);
  674.   if (!transArray)
  675.     return;
  676.   var trans = Components.classes[TRANSFERABLE_CONTRACTID].createInstance(Components.interfaces.nsITransferable);
  677.   if (!trans)
  678.     return;
  679.   
  680.   // Adding URL flavor
  681.   trans.addDataFlavor("text/x-moz-url");
  682.   var col = tree.columns[urlField];
  683.   var url = tree.view.getCellText(row, col);
  684.   col = tree.columns[descField];
  685.   var desc = tree.view.getCellText(row, col);
  686.   var stringURL = Components.classes[STRING_CONTRACTID].createInstance(Components.interfaces.nsISupportsString);
  687.   stringURL.data = url + "\n"+desc;
  688.   trans.setTransferData("text/x-moz-url", stringURL, stringURL.data.length * 2 );
  689.   transArray.AppendElement(trans.QueryInterface(Components.interfaces.nsISupports));
  690.  
  691.   dragService.invokeDragSession(event.target, transArray, null, dragService.DRAGDROP_ACTION_NONE);
  692. }
  693.  
  694. //******** Image Stuff
  695. function getSelectedImage(tree)
  696. {
  697.   if (!imageView.rowCount) return null;
  698.  
  699.   // Only works if only one item is selected
  700.   var clickedRow = tree.currentIndex;
  701.   // image-node
  702.   return imageView.data[clickedRow][4];
  703. }
  704.  
  705. function saveMedia()
  706. {
  707.   var tree = document.getElementById("imagetree");
  708.   var item = getSelectedImage(tree);
  709.   var url = imageView.data[tree.currentIndex][0];
  710.  
  711.   if (url)
  712.     // XXX Firefox specfic
  713.     saveURL(url, null, 'SaveImageTitle', false, false, makeURI(item.baseURI));
  714. }
  715.  
  716. function onImageSelect()
  717. {
  718.   var tree = document.getElementById("imagetree");
  719.   var saveAsButton = document.getElementById("imagesaveasbutton");
  720.  
  721.   if (tree.view.selection.count == 1)
  722.   {
  723.     makePreview(tree.view.selection.currentIndex);
  724.     saveAsButton.setAttribute("disabled", "false");
  725.   }
  726.   else
  727.     saveAsButton.setAttribute("disabled", "true");
  728. }
  729.  
  730. function makePreview(row)
  731. {
  732.   var imageTree = document.getElementById("imagetree");
  733.   var item = getSelectedImage(imageTree);
  734.   var col = imageTree.columns["image-address"];
  735.   var url = imageView.getCellText(row, col);
  736.   // image-bg
  737.   var isBG = imageView.data[row][5];
  738.  
  739.   setItemValue("imageurltext", url);
  740.  
  741.   if (item.hasAttribute("title"))
  742.     setItemValue("imagetitletext", item.title, gStrings.emptyString);
  743.   else
  744.     setItemValue("imagetitletext", null);
  745.  
  746.   if (item.hasAttribute("longDesc"))
  747.     setItemValue("imagelongdesctext", item.longDesc, gStrings.emptyString);
  748.   else
  749.     setItemValue("imagelongdesctext", null);
  750.  
  751.   if (item.hasAttribute("alt"))
  752.     setItemValue("imagealttext", item.alt, gStrings.emptyString);
  753.   else if (item instanceof nsIImageElement || isBG)
  754.     setItemValue("imagealttext", null);
  755.   else
  756.     setItemValue("imagealttext", getValueText(item));
  757.  
  758.   // get cache info
  759.   var sourceText = theBundle.getString("generalNotCached");
  760.   var expirationText;
  761.   var sizeText;
  762.  
  763.   var pageSize = 0; 
  764.   var kbSize = 0;
  765.   var expirationTime = 0;
  766.   var expirationDate = null;
  767.  
  768.   document.getElementById("imagesourcetext").removeAttribute("disabled");
  769.  
  770.   var cacheKey = url.replace(/#.*$/, "");
  771.   try
  772.   {
  773.     var cacheEntryDescriptor = httpCacheSession.openCacheEntry(cacheKey, Components.interfaces.nsICache.ACCESS_READ, false);   // open for READ, in non-blocking mode
  774.     if (cacheEntryDescriptor)
  775.     {
  776.       switch(cacheEntryDescriptor.deviceID)
  777.       {
  778.         case "disk":
  779.           sourceText = theBundle.getString("generalDiskCache");
  780.           break;
  781.         case "memory":
  782.           sourceText = theBundle.getString("generalMemoryCache");
  783.           break;
  784.         default:
  785.           sourceText = cacheEntryDescriptor.deviceID;
  786.           break;
  787.       }
  788.     }
  789.   }
  790.   catch(ex)
  791.   {
  792.     try
  793.     {
  794.       cacheEntryDescriptor = ftpCacheSession.openCacheEntry(cacheKey, Components.interfaces.nsICache.ACCESS_READ, false);   // open for READ, in non-blocking mode
  795.       if (cacheEntryDescriptor)
  796.       {
  797.         switch(cacheEntryDescriptor.deviceID)
  798.         {
  799.           case "disk":
  800.             sourceText = theBundle.getString("generalDiskCache");
  801.             break;
  802.           case "memory":
  803.             sourceText = theBundle.getString("generalMemoryCache");
  804.             break;
  805.           default:
  806.             sourceText = cacheEntryDescriptor.deviceID;
  807.             break;
  808.         }
  809.       }
  810.     }
  811.     catch(ex2)
  812.     {
  813.     }
  814.   }
  815.  
  816.   // find out the file size and expiration date
  817.   if (cacheEntryDescriptor)
  818.   {
  819.     pageSize = cacheEntryDescriptor.dataSize;
  820.     kbSize = pageSize / 1024;
  821.     sizeText = theBundle.getFormattedString("generalSize", [formatNumber(Math.round(kbSize*100)/100), formatNumber(pageSize)]);
  822.  
  823.     expirationText = formatDate(cacheEntryDescriptor.expirationTime*kmsPerSec, null);
  824.   }
  825.  
  826.   setItemValue("imageexpirestext", expirationText, gStrings.noExpiration);
  827.   setItemValue("imagesizetext", sizeText, gStrings.unknown);
  828.   setItemValue("imagesourcetext", sourceText, theBundle.getString("generalNotCached"));
  829.  
  830.   var mimeType;
  831.   if (item instanceof nsIObjectElement || item instanceof nsIEmbedElement || item instanceof nsILinkElement)
  832.     mimeType = item.type;
  833.   if (!mimeType)
  834.     mimeType = getContentTypeFromImgRequest(item) ||
  835.                getContentTypeFromHeaders(cacheEntryDescriptor);
  836.  
  837.   setItemValue("imagetypetext", mimeType, gStrings.unknown);
  838.  
  839.   var imageContainer = document.getElementById("theimagecontainer");
  840.   var oldImage = document.getElementById("thepreviewimage");
  841.  
  842.   const regex = /^(https?|ftp|file|gopher|about|chrome|resource):/;
  843.   var isProtocolAllowed = regex.test(url);
  844.   if (/^data:/.test(url) && /^image\//.test(mimeType))
  845.     isProtocolAllowed = true;
  846.  
  847.   var newImage = new Image();
  848.   newImage.setAttribute("id", "thepreviewimage");
  849.   var physWidth = 0, physHeight = 0;
  850.   var width = 0, height = 0;
  851.  
  852.   if ((item instanceof nsILinkElement || item instanceof nsIInputElement || item instanceof nsIImageElement || 
  853.       (item instanceof nsIObjectElement && /^image\//.test(mimeType)) || isBG) && isProtocolAllowed)
  854.   {
  855.     newImage.setAttribute("src", url);
  856.     physWidth = newImage.width || 0;
  857.     physHeight = newImage.height || 0;
  858.  
  859.     // "width" and "height" attributes must be set to newImage,
  860.     // even if there is no "width" or "height attribute in item;
  861.     // otherwise, the preview image cannot be displayed correctly.
  862.     if (!isBG)
  863.     {
  864.       newImage.width = ("width" in item && item.width) || newImage.naturalWidth;
  865.       newImage.height = ("height" in item && item.height) || newImage.naturalHeight;
  866.     }
  867.     else
  868.     {
  869.       // the Width and Height of an HTML tag should not be use for its background image
  870.       // (for example, "table" can have "width" or "height" attributes)
  871.       newImage.width = newImage.naturalWidth;
  872.       newImage.height = newImage.naturalHeight;
  873.     }
  874.  
  875.     width = newImage.width;
  876.     height = newImage.height;
  877.  
  878.     document.getElementById("theimagecontainer").collapsed = false
  879.     document.getElementById("brokenimagecontainer").collapsed = true;
  880.   } 
  881.   else 
  882.   {
  883.     // fallback image for protocols not allowed (e.g., data: or javascript:) 
  884.     // or elements not [yet] handled (e.g., object, embed).
  885.     document.getElementById("brokenimagecontainer").collapsed = false;
  886.     document.getElementById("theimagecontainer").collapsed = true;
  887.   }
  888.  
  889.   var imageSize = document.getElementById("imageSize");
  890.   if (url)
  891.   {
  892.     imageSize.value = theBundle.getFormattedString("mediaSize", [formatNumber(width), formatNumber(height)]);
  893.     imageSize.removeAttribute("disabled");
  894.   }
  895.   else
  896.   {
  897.     imageSize.value = gStrings.notSet;
  898.     imageSize.setAttribute("disabled", "true");
  899.   }
  900.  
  901.   var physRow = document.getElementById("physRow");
  902.   if (width != physWidth || height != physHeight)
  903.   {
  904.     physRow.collapsed = false;
  905.     document.getElementById("physSize").value = theBundle.getFormattedString("mediaSize", [formatNumber(physWidth), formatNumber(physHeight)]);
  906.   }
  907.   else
  908.     physRow.collapsed = true;
  909.  
  910.   imageContainer.removeChild(oldImage);
  911.   imageContainer.appendChild(newImage);
  912. }
  913.  
  914. function getContentTypeFromHeaders(cacheEntryDescriptor)
  915. {
  916.   if (!cacheEntryDescriptor)
  917.     return null;
  918.  
  919.   return (/^Content-Type:\s*(.*?)\s*(?:\;|$)/mi
  920.           .exec(cacheEntryDescriptor.getMetaDataElement("response-head")))[1];
  921. }
  922.  
  923. function getContentTypeFromImgRequest(item)
  924. {
  925.   var httpRequest;
  926.  
  927.   try
  928.   {
  929.     var imageItem = item.QueryInterface(nsIImageLoadingContent);
  930.     var imageRequest = imageItem.getRequest(nsIImageLoadingContent.CURRENT_REQUEST);
  931.     if (imageRequest) 
  932.       httpRequest = imageRequest.mimeType;
  933.   }
  934.   catch (ex)
  935.   {
  936.     // This never happened.  ;)
  937.   }
  938.  
  939.   return httpRequest;
  940. }
  941.  
  942. //******** Other Misc Stuff
  943. // Modified from the Links Panel v2.3, http://segment7.net/mozilla/links/links.html
  944. // parse a node to extract the contents of the node
  945. function getValueText(node)
  946. {
  947.   var valueText = "";
  948.  
  949.   // form input elements don't generally contain information that is useful to our callers, so return nothing
  950.   if (node instanceof nsIInputElement || node instanceof nsISelectElement || node instanceof nsITextareaElement)
  951.     return valueText;
  952.  
  953.   // otherwise recurse for each child
  954.   var length = node.childNodes.length;
  955.   for (var i = 0; i < length; i++)
  956.   {
  957.     var childNode = node.childNodes[i];
  958.     var nodeType = childNode.nodeType;
  959.  
  960.     // text nodes are where the goods are
  961.     if (nodeType == Node.TEXT_NODE)
  962.       valueText += " " + childNode.nodeValue;
  963.     // and elements can have more text inside them
  964.     else if (nodeType == Node.ELEMENT_NODE)
  965.     {
  966.       // images are special, we want to capture the alt text as if the image weren't there
  967.       if (childNode instanceof nsIImageElement)
  968.         valueText += " " + getAltText(childNode);
  969.       else
  970.         valueText += " " + getValueText(childNode);
  971.     }
  972.   }
  973.  
  974.   return stripWS(valueText);
  975. }
  976.  
  977. // Copied from the Links Panel v2.3, http://segment7.net/mozilla/links/links.html
  978. // traverse the tree in search of an img or area element and grab its alt tag
  979. function getAltText(node)
  980. {
  981.   var altText = "";
  982.   
  983.   if (node.alt)
  984.     return node.alt;
  985.   var length = node.childNodes.length;
  986.   for (var i = 0; i < length; i++)
  987.     if ((altText = getAltText(node.childNodes[i]) != undefined))  // stupid js warning...
  988.       return altText;
  989.   return "";
  990. }
  991.  
  992. // Copied from the Links Panel v2.3, http://segment7.net/mozilla/links/links.html
  993. // strip leading and trailing whitespace, and replace multiple consecutive whitespace characters with a single space
  994. function stripWS(text)
  995. {
  996.   var middleRE = /\s+/g;
  997.   var endRE = /(^\s+)|(\s+$)/g;
  998.  
  999.   text = text.replace(middleRE, " ");
  1000.   return text.replace(endRE, "");
  1001. }
  1002.  
  1003. function setItemValue(id, value, other)
  1004. {
  1005.   var item = document.getElementById(id);
  1006.   item.value = value || other || gStrings.notSet;
  1007.   if (value)
  1008.     item.removeAttribute("disabled");
  1009.   else
  1010.     item.setAttribute("disabled", "true");
  1011. }
  1012.  
  1013. function formatNumber(number)
  1014. {
  1015.   return (+number).toLocaleString();  // coerce number to a numeric value before calling toLocaleString()
  1016. }
  1017.  
  1018. function formatDate(datestr, unknown)
  1019. {
  1020.   var date = new Date(datestr);
  1021.   return (date.valueOf()) ? dateService.FormatDateTime("", dateService.dateFormatLong, dateService.timeFormatSeconds, date.getFullYear(), date.getMonth()+1, date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds()) : unknown;
  1022. }
  1023.  
  1024. function doCopy()
  1025. {
  1026.   if (!gClipboardHelper) 
  1027.     return;
  1028.  
  1029.   var elem = document.commandDispatcher.focusedElement;
  1030.  
  1031.   if (elem && "treeBoxObject" in elem)
  1032.   {
  1033.     var view = elem.treeBoxObject.view;
  1034.     var selection = view.selection;
  1035.     var text = [], tmp = '';
  1036.     var min = {}, max = {};
  1037.  
  1038.     var count = selection.getRangeCount();
  1039.  
  1040.     for (var i = 0; i < count; i++)
  1041.     {
  1042.       selection.getRangeAt(i, min, max);
  1043.  
  1044.       for (var row = min.value; row <= max.value; row++)
  1045.       {
  1046.         view.performActionOnRow("copy", row);
  1047.  
  1048.         tmp = elem.getAttribute("copybuffer");
  1049.         if (tmp)
  1050.           text.push(tmp);
  1051.         elem.removeAttribute("copybuffer");
  1052.       }
  1053.     }
  1054.     gClipboardHelper.copyString(text.join("\n"));
  1055.   }
  1056. }
  1057.  
  1058. function doSelectAll()
  1059. {
  1060.   var elem = document.commandDispatcher.focusedElement;
  1061.  
  1062.   if (elem && "treeBoxObject" in elem)
  1063.     elem.treeBoxObject.view.selection.selectAll();
  1064. }
  1065.  
  1066.